home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
net
/
ipxsrc
/
ipxnet.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-13
|
6KB
|
328 lines
// ipxnet.c
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <process.h>
#include <values.h>
#include "ipxnet.h"
/*
=============================================================================
IPX PACKET DRIVER
=============================================================================
*/
packet_t packets[NUMPACKETS];
nodeadr_t nodeadr[MAXNETNODES+1]; // first is local, last is broadcast
nodeadr_t remoteadr; // set by each GetPacket
localadr_t localadr; // set at startup
int socketid = 0x869c; // 0x869c is the official DOOM socket
union REGS regs; // scratch for int86 calls
struct SREGS sregs;
unsigned short enteripx[2];
long localtime; // for time stamp in packets
long remotetime;
//===========================================================================
char *hex = "0123456789abcdef";
void PrintAddress (nodeadr_t *adr, char *str)
{
int i;
for (i=0 ; i<6 ; i++)
{
*str++ = hex[adr->node[i]>>4];
*str++ = hex[adr->node[i]&15];
}
*str = 0;
}
int OpenSocket(short socketNumber)
{
regs.x.bx = 0;
regs.h.al = 0; // longevity
regs.x.dx = socketNumber;
int86(0x7A,®s,®s);
if (regs.h.al)
Error ("OpenSocket: 0x%x",regs.h.al);
return regs.x.dx;
}
void CloseSocket(short socketNumber)
{
regs.x.bx = 1;
regs.x.dx = socketNumber;
int86(0x7A,®s,®s);
}
void ListenForPacket(ECB *ecb)
{
regs.x.si = FP_OFF(ecb);
sregs.es = FP_SEG(ecb);
regs.x.bx = 4;
int86x (0x7a,®s,®s,&sregs);
if (regs.h.al)
Error ("ListenForPacket: 0x%x",regs.h.al);
}
void GetLocalAddress (void)
{
regs.x.si = FP_OFF(&localadr);
sregs.es = FP_SEG(&localadr);
regs.x.bx = 9;
int86x (0x7a,®s,®s,&sregs);
if (regs.h.al)
Error ("Get inet addr: 0x%x",regs.h.al);
}
/*
====================
=
= InitNetwork
=
====================
*/
void InitNetwork (void)
{
int i,j;
//
// get IPX function address
//
regs.x.ax = 0x7a00;
int86x (0x2f,®s,®s,&sregs);
if ( regs.h.al != 0xff)
Error ("IPX not detected\n");
enteripx[0] = regs.x.di;
enteripx[1] = sregs.es;
//
// allocate a socket for sending and receiving
//
i = CheckParm ("-port");
if (i>0 && i<_argc-1)
{
socketid = atoi (_argv[i+1]);
printf ("Using alternate port %i for network\n",socketid);
}
socketid = OpenSocket ( (socketid>>8) + ((socketid&255)<<8) );
GetLocalAddress ();
//
// set up several receiving ECBs
//
memset (packets,0,NUMPACKETS*sizeof(packet_t));
for (i=1 ; i<NUMPACKETS ; i++)
{
packets[i].ecb.InUseFlag = 0x1d;
packets[i].ecb.ECBSocket = socketid;
packets[i].ecb.FragmentCount = 1;
packets[i].ecb.fAddress[0] = FP_OFF(&packets[i].ipx);
packets[i].ecb.fAddress[1] = FP_SEG(&packets[i].ipx);
packets[i].ecb.fSize = sizeof(packet_t)-sizeof(ECB);
ListenForPacket (&packets[i].ecb);
}
//
// set up a sending ECB
//
memset (&packets[0],0,sizeof(packets[0]));
packets[0].ecb.ECBSocket = socketid;
packets[0].ecb.FragmentCount = 1;
packets[0].ecb.fAddress[0] = FP_OFF(&packets[0].ipx);
packets[0].ecb.fAddress[1] = FP_SEG(&packets[0].ipx);
for (j=0 ; j<4 ; j++)
packets[0].ipx.dNetwork[j] = localadr.network[j];
packets[0].ipx.dSocket[0] = socketid&255;
packets[0].ipx.dSocket[1] = socketid>>8;
// known local node at 0
for (i=0 ; i<6 ; i++)
nodeadr[0].node[i] = localadr.node[i];
// broadcast node at MAXNETNODES
for (j=0 ; j<6 ; j++)
nodeadr[MAXNETNODES].node[j] = 0xff;
}
/*
====================
=
= ShutdownNetwork
=
====================
*/
void ShutdownNetwork (void)
{
CloseSocket (socketid);
}
/*
==============
=
= SendPacket
=
= A destination of MAXNETNODES is a broadcast
==============
*/
void SendPacket (int destination)
{
int j;
// find a free packet buffer to use
while (packets[0].ecb.InUseFlag)
{
}
// set the time
packets[0].time = localtime;
// set the address
for (j=0 ; j<6 ; j++)
packets[0].ipx.dNode[j] = packets[0].ecb.ImmediateAddress[j] =
nodeadr[destination].node[j];
// set the length (ipx + time + datalength)
packets[0].ecb.fSize = sizeof(IPXPacket) + 4 + doomcom.datalength + 4;
// put the data into an ipx packet
memcpy (&packets[0].data, &doomcom.data, doomcom.datalength);
// send the packet
regs.x.si = FP_OFF(&packets[0]);
sregs.es = FP_SEG(&packets[0]);
regs.x.bx = 3;
int86x (0x7a, ®s, ®s, &sregs);
if (regs.h.al)
Error ("SendPacket: 0x%x",regs.h.al);
}
unsigned short ShortSwap (unsigned short i)
{
return ((i&255)<<8) + ((i>>8)&255);
}
/*
==============
=
= GetPacket
=
= Returns false if no packet is waiting
=
==============
*/
int GetPacket (void)
{
int packetnum;
int i, j;
long besttic;
packet_t *packet;
// if multiple packets are waiting, return them in order by time
besttic = MAXLONG;
packetnum = -1;
doomcom.remotenode = -1;
for ( i = 1 ; i < NUMPACKETS ; i++)
{
if (packets[i].ecb.InUseFlag)
{
continue;
}
if (packets[i].time < besttic)
{
besttic = packets[i].time;
packetnum = i;
}
}
if (besttic == MAXLONG)
return 0; // no packets
packet = &packets[packetnum];
if (besttic == -1 && localtime != -1)
{
ListenForPacket (&packet->ecb);
return 0; // setup broadcast from other game
}
remotetime = besttic;
//
// got a good packet
//
if (packet->ecb.CompletionCode)
Error ("GetPacket: ecb.ComletionCode = 0x%x",packet->ecb.CompletionCode);
// set remoteadr to the sender of the packet
memcpy (&remoteadr, packet->ipx.sNode, sizeof(remoteadr));
for (i=0 ; i<doomcom.numnodes ; i++)
if (!memcmp(&remoteadr, &nodeadr[i], sizeof(remoteadr)))
break;
if (i < doomcom.numnodes)
doomcom.remotenode = i;
else
{
if (localtime != -1)
{ // this really shouldn't happen
ListenForPacket (&packet->ecb);
return 0;
}
}
// copy out the data
doomcom.datalength = ShortSwap(packet->ipx.PacketLength) - 38;
memcpy (&doomcom.data, &packet->data, doomcom.datalength);
// repost the ECB
ListenForPacket (&packet->ecb);
return 1;
}